from knglib.parseconfig import ConfigParser
from knglib.baselib     import md5sum
from tarfile            import TarFile
from os                 import path
from variables          import PACKAGE_CONFIG_DEFAULT_HEADER,  PACKAGE_CONFIG_FILE,      \
                               PACKAGE_CONFIG_REQUIRED_FIELDS, PACKAGE_DESCRIPTION_FILE, \
                               PACKAGE_IMPORTANT_FILES,        PACKAGES_CATEGORIES,      \
                               PACKAGES_INSTALLED_DIR,         PACKAGES_MD5,             \
                               PACKAGES_MD5SUM_LIST,           PACKAGES_PATH


class PackageException(Exception):
    """Exception disparada quando o pacote nao
    contiver os arquivos necessarios."""
    def __init__(self, mensagem):
        Exception.__init__(self, mensagem)




class PackageConfigException(Exception):
    """Exception disparada quando existir alguma
    "irregularidade" no arquivo de configuracao.
    (package.conf)"""
    def __init__(self, mensagem):
        Exception.__init__(self, mensagem)




class Package(TarFile):
    """Interface para os pacotes dos Icones Magicos."""
    def __init__(self, fileobj):
        TarFile.__init__(self, fileobj=fileobj);
        self.__fp = fileobj
        self.__filenames = set(self.getnames())
        self.__config = ConfigParser()
        
        #Checa se os arquivos importantes estao persentes
        check = True
        for file in PACKAGE_IMPORTANT_FILES:
            check &= file in self.__filenames
            if not check:
                raise PackageException('Invalid KNG package.')
        
        #Faz a leitura do arquivo package.conf e checa se
        #os campos obrigatorios estao presentes
        conf = self.getmember(PACKAGE_CONFIG_FILE)
        self.__fp.seek(conf.offset + 512)
        self.__config.parsestr(self.__fp.read(conf.size))
        
        gs = self.__config.getSection(PACKAGE_CONFIG_DEFAULT_HEADER)
        if gs is None:
            raise PackageConfigException('General section is not present.')
        
        check = True
        opts = gs.getOptionsName()
        for opt in PACKAGE_CONFIG_REQUIRED_FIELDS:
            check &= opt in opts
            if not check:
                raise PackageConfigException('Required field \'%s\' is not present in package.conf.' % opt)
        
        #Calcula o md5sum do pacote
        self.__fp.seek(0)
        self.__md5sum = md5sum(fileobj=self.__fp).lower()
        
        #Obtem o nome do arquivo
        self.__fname = path.basename(fileobj.name).lower()
        
        #Obtem os dados do pacote
        gs = self.__config.getSection(PACKAGE_CONFIG_DEFAULT_HEADER)
        self.__name          = gs.get('Name')
        self.__author        = gs.get('Author')
        self.__category      = gs.get('Category')
        self.__description   = gs.get('Description')
        self.__referencefile = gs.get('ReferenceFile')
        self.__link          = gs.get('Link')
        
        #Checa se a categoria do pacote e valida
        if not self.__category.lower() in PACKAGES_CATEGORIES:
            raise PackageConfigException('\'%s\' is not a valid category.' % self.__category)
        
        #Reuni a lista de URLs de GetDebs
        self.__getdebs = []
        gds = self.__config.getSection('GetDebs')
        if gds is not None:
            self.__getdebs = gds.getLines()
        
        #Obtem a lista de pacotes para serem instalados
        self.__aptpackages = []
        op = self.__config.get(PACKAGE_CONFIG_DEFAULT_HEADER, 'AptPackages')
        if op is not None:
            self.__aptpackages = op.split()
        
        #Obtem as informacoes detalhadas do pacote
        #conteudo de package.article
        self.__article = None
        if PACKAGE_DESCRIPTION_FILE in self.__filenames:
            desc = self.getmember(PACKAGE_DESCRIPTION_FILE)
            self.__fp.seek(desc.offset + 512)
            self.__article = self.__fp.read(desc.size)
        
        #Obtem as linhas do section AptLists
        self.__aptlists = []
        als = self.__config.getSection('AptLists')
        if als is not None:
            self.__aptlists = als.getLines()
        
        #Obtem as linhas do section AptKeys
        self.__aptkeys = []
        aks = self.__config.getSection('AptKeys')
        if aks is not None:
            self.__aptkeys = aks.getLines()
        
        #Obtem a lista dos arquivos no diretorio: desktop/
        list = [path.split(ln) for ln in self.__filenames]
        self.__desktopfiles = [f for (d, f) in list if d == 'desktop' and f != '']
    
    
    def getArticle(self):
        """Retorna o conteudo do arquivo package.article.
        Caso o arquivo nao exista None e retornado."""
        return self.__article
    
    
    def getDebList(self):
        """Retorna a lista das URLs contidas no header
        GetDebs."""
        return self.__getdebs
    
    
    def getName(self):
        """Retorna o nome interno do pacote contido em
        package.conf."""
        return self.__name
    
    
    def getAuthor(self):
        """Retorna o autor do pacote."""
        return self.__author
    
    
    def getCategory(self):
        """Retorna a categoria do pacote."""
        return self.__category
    
    
    def getDescription(self):
        """Retorna a descricao do pacote."""
        return self.__description
    
    
    def getReferenceFile(self):
        """Retorna o nome do arquivo de referencia
        do pacote."""
        return self.__referencefile
    
    
    def getLink(self):
        """Retorna a URL do site do projeto ou autor
        do programa."""
        return self.__link
    
    
    def getMD5(self):
        """Retorna a md5sum do pacote"""
        return self.__md5sum
    
    
    def getFilename(self):
        """Retorna o nome do arquivo"""
        return self.__fname
    
    
    def getAptKeys(self):
        """Retorna a lista das keys contidas no
        header AptKeys."""
        return self.__aptkeys
    
    
    def getAptLists(self):
        """Retorna a lista de repositorios contidas
        no header AptLists."""
        return self.__aptlists
    
    
    def getDesktopFiles(self):
        """Retorna a lista com o nome dos arquivos
        contidos no diretorio desktop/."""
        return self.__desktopfiles
    
    
    def getPackages(self):
        """Retorna a lista de pacotes de AptPackages."""
        return self.__aptpackages

